use std::ops::Deref;
use std::rc::Rc;
use std::sync::Arc;

/// 除了普通的引用 (借用〉类型 ， Rust 还提供具有移动语义(引用语义)的智能指针 。
/// 智能指针和普通引用的区别之一就是所有权的不同。智能指针拥有资源的所有权，而普通引用只是对所有权的借用。
/// 只能指针最主要的两个trait: Deref Drop
pub fn start() {
    let a = Box::new("hello".to_owned());
    let b = Box::new("rust".to_owned());
    let c = *a;
    let d = *b;

    // 这里的气和* b 操作相当于 *(a.deref)和*(b.deref)操作。
    // 对于 Box<T>类型来说 ，如果包含的类型T属于复制语义，则执行按位复制;如果属于移动语义，则移动所有权。
    println!("{} {}", c, d);

    let test_deref = TestDeref {
        value: TestDeref { value: T },
    };
    println!("{:?}", test_deref);

    // move occurs because value has type `TestDeref<se_5_47::T>`,
    // which does not implement the `Copy` trait
    // 为什么Box可以直接解引用移动？
    // 这种对 Box<T>使用操作符(*)进行解引用而转移所有权的行为，被称为解引用移动，
    // 理论上应该使用 trait DerefMove定义此行为，这也是官方团队未来打算做的，
    // 但实际上 Rust 源码中并不存在此 trait。 目前支持此行为的智能指针只有 Box<T>
    // let e = *test_deref;
    // println!("{:?}", e.value);
    let test_deref_two = &TestDeref {
        value: TestDeref { value: T },
    };
    println!("{:?}", test_deref_two);

    // Rc<T>或 Arc<T>智能指针也不支持解引用移动
    let r = Rc::new("rust".to_string());
    let a = Arc::new("hello".to_string());
    // let x = *r;
    // println!("{}", x);
    println!("{} {}", r, a);
}

#[derive(Debug)]
struct TestDeref<T> {
    value: T,
}

impl<T> Deref for TestDeref<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.value
    }
}

#[derive(Debug)]
struct T;

impl T {
    fn print(&self) {
        println!("这是 T");
    }
}
